<template>
  <div class="att-wrap" v-if="attachments && attachments.length">
    <div class="att-toolbar">
      <div class="left">
        <el-tag type="success" v-if="images.length"
          >图片 {{ images.length }}</el-tag
        >
        <el-tag type="info" v-if="others.length" class="ml8"
          >文件 {{ others.length }}</el-tag
        >
      </div>
      <div class="right">
        <el-button type="primary" @click="downloadAllZip" :loading="downloading"
          >批量下载（{{ attachments.length }}）</el-button
        >
      </div>
    </div>

    <!-- 图片宫格 -->
    <div v-if="images.length" class="img-grid">
      <el-image
        v-for="(img, idx) in images"
        :key="img.id || idx"
        class="img-thumb"
        :src="resolveUrl(img.fileUrl)"
        :alt="img.fileName"
        fit="cover"
        :preview-src-list="imgPreviewList"
        :initial-index="idx"
        hide-on-click-modal
        preview-teleported
      />
    </div>

    <!-- 其他文件 -->
    <div v-if="others.length" class="file-list">
      <el-card
        v-for="f in others"
        :key="f.id"
        shadow="hover"
        class="file-item"
        @dblclick="onDblClick(f)"
      >
        <div class="file-row">
          <el-icon class="file-ico"><Document /></el-icon>
          <div class="file-main">
            <div class="file-name" :title="f.fileName">{{ f.fileName }}</div>
            <div class="file-meta">
              <span>{{ formatSize(f.fileSize) }}</span>
              <span class="dot">·</span>
              <span>{{ f.fileType || "-" }}</span>
              <span class="dot">·</span>
              <span>{{ f.uploadTime || "" }}</span>
            </div>
          </div>
          <div class="file-ops">
            <el-button
              v-if="isPdf(f)"
              link
              type="primary"
              @click.stop="previewPdf(f)"
              >预览</el-button
            >
            <el-button link type="primary" @click.stop="openInNewTab(f)"
              >打开</el-button
            >
            <el-button link @click.stop="downloadOne(f)">下载</el-button>
          </div>
        </div>
      </el-card>
    </div>

    <!-- PDF 预览弹窗 -->
    <el-dialog
      v-model="pdfVisible"
      width="80%"
      top="4vh"
      :destroy-on-close="true"
      :close-on-click-modal="false"
      title="PDF 预览"
    >
      <div class="pdf-box">
        <iframe
          v-if="pdfSrc"
          :src="pdfSrc"
          frameborder="0"
          class="pdf-iframe"
        ></iframe>
        <el-empty v-else description="加载中..." />
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="js">
  import { computed, ref } from 'vue'
  import { ElMessage } from 'element-plus'
  import { Document } from '@element-plus/icons-vue'
  import axios from 'axios'
  import { downloadOrderAttachmentsZip } from '@/api/sbtz/attachment'
  import { parseFilenameFromCD, saveBlob } from '@/utils/generator/download'



  const props = defineProps({
    attachments: { type: Array, default: () => [] },
    orderId: [Number, String]
  })

  const BASE = import.meta.env.VITE_APP_BASE_API || ''
  const downloading = ref(false)

  const isImage = (a) => {
    const t = (a?.fileType || '').toLowerCase()
    if (t.startsWith('image/')) return true
    const n = (a?.fileName || '').toLowerCase()
    return /\.(png|jpe?g|gif|bmp|webp|svg)$/.test(n)
  }
  const isPdf = (a) => {
    const t = (a?.fileType || '').toLowerCase()
    if (t.includes('application/pdf')) return true
    const n = (a?.fileName || '').toLowerCase()
    return /\.pdf$/.test(n)
  }

  const images = computed(() => (props.attachments || []).filter(isImage))
  const others  = computed(() => (props.attachments || []).filter(a => !isImage(a)))

  const resolveUrl = (u) => {
    if (!u) return ''
    if (/^https?:\/\//i.test(u)) return u
    return `${BASE}${u.startsWith('/') ? '' : '/'}${u}`
  }
  const imgPreviewList = computed(() => images.value.map(img => resolveUrl(img.fileUrl)))

  const formatSize = (n) => {
    if (!n || n <= 0) return '-'
    const units = ['B', 'KB', 'MB', 'GB']
    let i = 0, v = n
    while (v >= 1024 && i < units.length - 1) { v /= 1024; i++ }
    return `${v.toFixed(i === 0 ? 0 : 1)} ${units[i]}`
  }

  const openInNewTab = (f) => window.open(resolveUrl(f.fileUrl), '_blank')

  const downloadBlob = (blob, fileName) => {
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = fileName || 'download'
    a.style.display = 'none'
    document.body.appendChild(a)
    a.click()
    URL.revokeObjectURL(url)
    a.remove()
  }

  const downloadOne = async (f) => {
    try {
      const res = await axios.get(resolveUrl(f.fileUrl), { responseType: 'blob' })
      downloadBlob(res.data, f.fileName)
    } catch (e) {
      ElMessage.error('下载失败')
    }
  }

  const onDblClick = (f) => {
    if (isPdf(f)) previewPdf(f)
    else openInNewTab(f)
  }

  /** PDF 预览（优先 blob，兼容鉴权 & 跨域受限时降级到新窗口） */
  const pdfVisible = ref(false)
  const pdfSrc = ref('')

  const previewPdf = async (f) => {
    const url = resolveUrl(f.fileUrl)
    pdfSrc.value = ''
    pdfVisible.value = true
    try {
      const res = await axios.get(url, { responseType: 'blob' })
      // 如果服务返回的不是 PDF，也回退
      const type = (res.headers['content-type'] || '').toLowerCase()
      if (!type.includes('application/pdf')) {
        // 仍然尝试用新窗口打开
        window.open(url, '_blank')
        pdfVisible.value = false
        return
      }
      const obj = URL.createObjectURL(res.data)
      pdfSrc.value = obj
    } catch (e) {
      // 跨域或鉴权失败时，降级为新窗口直开
      window.open(url, '_blank')
      pdfVisible.value = false
    }
  }

  // 批量下载（后端打包ZIP）
  const downloadAllZip = async () => {
  if (!props.orderId) return
  try {
    downloading.value = true
    const res = await downloadOrderAttachmentsZip({ orderId: props.orderId })
    // 有的项目 request 封装会直接返回 res（含 headers），有的只返回 res.data（Blob）
    const blob = res?.data instanceof Blob ? res.data : res
    const cd = res?.headers?.['content-disposition'] || res?.headers?.['Content-Disposition']
    const filename = parseFilenameFromCD(cd, `工单${props.orderId}-附件.zip`)
    saveBlob(blob, filename)
  } finally {
    downloading.value = false
  }
}
</script>

<style scoped>
.att-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.ml8 {
  margin-left: 8px;
}
.img-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
  margin-bottom: 12px;
}
.img-thumb {
  width: 100%;
  height: 110px;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.07);
}
.file-list {
  display: grid;
  gap: 10px;
}
.file-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.file-ico {
  font-size: 22px;
}
.file-main {
  flex: 1;
  min-width: 0;
}
.file-name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.file-meta {
  font-size: 12px;
  color: #999;
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.dot {
  opacity: 0.5;
}
.file-ops {
  white-space: nowrap;
}
.pdf-box {
  height: 75vh;
}
.pdf-iframe {
  width: 100%;
  height: 100%;
}
</style>
